package com.xuecheng.manage_cms.service;

import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.xuecheng.framework.domain.cms.CmsPage;
import com.xuecheng.framework.domain.cms.CmsTemplate;
import com.xuecheng.framework.domain.cms.response.CmsCode;
import com.xuecheng.framework.exception.ExceptionCast;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.framework.model.response.QueryResult;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.manage_cms.dao.CmsPageRepository;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.Optional;

/**
 * 页面管理实现层
 */
@Service
public class CmsPageService {
    @Autowired private CmsPageRepository cmsPageRepository;

    @Autowired private RestTemplate restTemplate;

    @Autowired private GridFSBucket gridFSBucket;

    @Autowired private GridFsTemplate gridFsTemplate;

    @Autowired private CmsTemplateService cmsTemplateService;
    /**
     * 页面分页查询接口
     * @param page
     * @param size
     * @param cmsPage
     * @return
     */
    public QueryResponseResult findList(int page, int size, CmsPage cmsPage){

        //条件匹配器,
        ExampleMatcher exampleMatcher =ExampleMatcher.matching();
        //创建模糊条件查询
        exampleMatcher =exampleMatcher.withMatcher("pageAliase",ExampleMatcher.GenericPropertyMatchers.contains());
        //创建条件实例，有意思的是实体类字段有值的时候自动默认是精确查询，所以有时候可能要过滤一下
        Example<CmsPage> example= Example.of(cmsPage,exampleMatcher);
        Pageable pageable= PageRequest.of(page,size);

        Page<CmsPage> list= cmsPageRepository.findAll(example,pageable);
        QueryResult<CmsPage> queryResult=new QueryResult<CmsPage>();
        queryResult.setList(list.getContent());
        queryResult.setTotal(list.getTotalElements());
        queryResult.setTotalPage(list.getTotalPages());
        return new QueryResponseResult(CommonCode.SUCCESS,queryResult);

    }

    /**
     * 页面新增接口
     * @param cmsPage
     * @return
     */
    public ResponseResult<CmsPage> add(CmsPage cmsPage){
        //先查询有没有此页面
        CmsPage cmsPage1=cmsPageRepository.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName(),cmsPage.getSiteId(),cmsPage.getPageWebPath());
        if(cmsPage1==null){
            cmsPage.setPageId(null);
            cmsPage.setPageCreateTime(new Date());
            cmsPageRepository.save(cmsPage);
            return  new ResponseResult(CommonCode.SUCCESS,cmsPage);
        }
        return  new ResponseResult(CommonCode.FAIL,cmsPage);
    }


    /**
     * 根据id查询页面
     * @param id
     * @return
     */
    public ResponseResult<CmsPage> findById(String id){
        Optional<CmsPage> optional = cmsPageRepository.findById(id);
        return new ResponseResult(CommonCode.SUCCESS,optional.get());
    }

    /**
     * 更新页面信息
     * @param cmsPage
     * @return
     */
    public ResponseResult<CmsPage> update(CmsPage cmsPage) {
        //根据id查询页面信息
        CmsPage one = cmsPageRepository.findById(cmsPage.getPageId()).get();
            if (one != null) {
                //更新模板id
                one.setTemplateId(cmsPage.getTemplateId());
                //更新所属站点
                one.setSiteId(cmsPage.getSiteId());
                //更新页面别名
                one.setPageAliase(cmsPage.getPageAliase());
                //更新页面名称
                one.setPageName(cmsPage.getPageName());
                //更新访问路径
                one.setPageWebPath(cmsPage.getPageWebPath());
                //更新物理路径
                one.setPagePhysicalPath(cmsPage.getPagePhysicalPath());
                //更新类型
                one.setPageType(cmsPage.getPageType());
                //更新数据Url
                one.setDataUrl(cmsPage.getDataUrl());
                //执行更新
                CmsPage save = cmsPageRepository.save(one);
                if (save != null) {
                    //返回成功
                    return new ResponseResult(CommonCode.SUCCESS, save);
                }
            }
        //返回失败
        return new ResponseResult(CommonCode.FAIL);
    }

    /**
     * 页面删除接口
     * @param id
     * @return
     */
    public ResponseResult delete(String  id){
        if(id!=null){
            cmsPageRepository.deleteById(id);
            return  new ResponseResult(CommonCode.SUCCESS);
        }
        return  new ResponseResult(CommonCode.FAIL);
    }


    /**
     * 页面静态化
     * @param pageId
     * @return
     */
    public String getPageHtml(String pageId){
        //查询页面信息
        CmsPage cmsPage = this.findById(pageId).getData();
        if(cmsPage == null){
            //页面不存在
            ExceptionCast.cast(CmsCode.CMS_PAGE_NOTEXISTS);
        }

        //获取页面模型数据
        Map model = this.getModelByPageId(cmsPage);
        if(model == null){
        //获取页面模型数据为空
            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_DATAISNULL);
        }
        //获取页面模板
        String templateContent = getTemplateByPageId(cmsPage);
        if(StringUtils.isEmpty(templateContent)){
        //页面模板为空
            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_TEMPLATEISNULL);
        }
        //执行静态化
        String html = generateHtml(templateContent, model);
        if(StringUtils.isEmpty(html)){
            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_HTMLISNULL);
        }
        return html;
    }

    /**
     * 页面静态化
     * @param template
     * @param model
     * @return
     */
    public String generateHtml(String template,Map model){
        try {
            //生成配置类
            Configuration configuration = new Configuration(Configuration.getVersion());
            //模板加载器
            StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
            stringTemplateLoader.putTemplate("template",template);
            //配置模板加载器
            configuration.setTemplateLoader(stringTemplateLoader);
            //获取模板
            Template template1 = configuration.getTemplate("template");
            String html = FreeMarkerTemplateUtils.processTemplateIntoString(template1, model);
            return html;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 获取页面模板
     * @param cmsPage
     * @return
     */
    public String getTemplateByPageId(CmsPage cmsPage){
        //页面模板
        String templateId = cmsPage.getTemplateId();
        if(StringUtils.isEmpty(templateId)){
        //页面模板为空
            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_TEMPLATEISNULL);
        }
        CmsTemplate cmsTemplate = cmsTemplateService.findById(templateId).getData();
        if(cmsTemplate!= null){
            //模板文件id
            String templateFileId = cmsTemplate.getTemplateFileId();
            //取出模板文件内容
            GridFSFile gridFSFile = gridFsTemplate.findOne(Query.query(Criteria.where("_id").is(templateFileId)));
            //打开下载流对象
            if(gridFSFile == null){
                ExceptionCast.cast(CmsCode.CMS_TEMPLATE_FILEISNULL);
            }
            GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(gridFSFile.getObjectId());
            //创建GridFsResource
            GridFsResource gridFsResource = new GridFsResource(gridFSFile,gridFSDownloadStream);
            try {
                String content = IOUtils.toString(gridFsResource.getInputStream(), "utf-8");
                return content;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 获取页面模型数据
     * @param cmsPage
     * @return
     */
    public Map getModelByPageId(CmsPage cmsPage){

        //取出dataUrl
        String dataUrl = cmsPage.getDataUrl();
        if(StringUtils.isEmpty(dataUrl)){
            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_DATAURLISNULL);
        }
        ResponseEntity<Map> forEntity = restTemplate.getForEntity(dataUrl, Map.class);
        Map body = forEntity.getBody();
        return body;
    }


}
